#include "statemanager.h"

using std::string;
using std::map;
using std::vector;

StateManager& StateManager::getInstance()
{
	static StateManager instance;
	return instance;
}

void StateManager::registerState(const string name, State* state) throw(StateException)
{
	if (states_.find(name) != states_.end())
		throw StateException("Cannot register state. State " + name + " already exist.");

	states_[name] = state;
}

State* StateManager::unregisterState(const string name) throw(StateException)
{
	map<string, State*>::iterator it = states_.find(name);
	if (it == states_.end())
		throw StateException("Cannot unregister state. State " + name + " doesn't exist.");


	if (!stack_.empty() && !stack_.back().compare(name))
		throw StateException("Cannot unregister active state.");

	State* state = states_[name];
	states_.erase(it);

	return state;
}

void StateManager::setState(const string name) throw(StateException)
{
	try {
		popState();
	}
	catch (StateException &e) {}
	pushState(name);
}

State* StateManager::getActiveState() throw(StateException)
{
	if (stack_.empty())
		throw StateException("There is no active state.");

	return states_[stack_.back()];
}

void StateManager::pushState(const std::string name) throw(StateException)
{
	map<string, State*>::iterator it = states_.find(name);
	if (it == states_.end())
		throw StateException("State " + name + " doesn't exist.");

	try {
		getActiveState()->pause();
	} catch (StateException &e) {}

	stack_.push_back(name);
	it->second->enter();
}

void StateManager::popState() throw(StateException)
{
	if (stack_.empty())
		throw StateException("There is no active state.");

	getActiveState()->exit();
	stack_.pop_back();
	try {
		getActiveState()->resume();
	} catch (StateException &e) {}
}
